#ifndef COMMUNICATIONS_COMMUNICATION_H
#define COMMUNICATIONS_COMMUNICATION_H
#include <stdint.h>
#include <string>
#include <utils/lock.h>
#include <atomic>
#include <memory>
#include <thread>
#include <functional>

namespace communication {
class Communication {
public:
    Communication();
    virtual ~Communication() = default;

    typedef enum { CT_TCP = 1, CT_UDP, CT_HTTP } CT_TYPE_t;

    static std::shared_ptr<Communication> GetCommunicationInstance(int protoId, bool isTls = false);
    bool IsRun() const;
    void Start(const std::string &host, int port = 0, int32_t timeout = 3000);
    void Stop();
    void Run();
    bool Send(const char *buf, int32_t len);
    void OnStatus(const std::function<void(bool)> &onStatus);
    void OnReceive(const std::function<void(char *buf, int32_t len)> &onReceive);
    virtual bool IsConnected() const = 0;
protected:
    void WaitForRecv();
    virtual std::string name() const = 0;
    virtual bool Connect(const std::string &host, int32_t port = 0) = 0;
    virtual void DisConnect() = 0;
    virtual int32_t SendData(const char *data, int32_t len) = 0;
    virtual int32_t RecvData(char reply[], int max = -1, int timeout = 3000) = 0;
protected:
    std::atomic<bool> bRun_{false};
    std::thread threadTask_;
    std::function<void(bool)> onStatus_ = nullptr;
    std::function<void(char *buf, int32_t len)> onReceive_ = nullptr;
    std::string host_;
    int32_t port_;
    int32_t timeout_ = 3000;
};
} // namespace communication
#endif